﻿using Bot.Domain.EndpointAPIResponseRecords;
using Bot.Domain.SessionChat;



using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bot.Domain.Report
{
    public enum EnumChatbotAnswerType
    {
        HighConfidenceAnswer = 0,
        PossibleAnser = 1,
        NoAnser = 2
    }

    public class ResponseItem : BaseReportInfoItem
    {
        public int Answers { get; set; }
        public int HighConfidenceAnswers { get; set; }
        public int PossibleAnswers { get; set; }
        public int NoAnswers { get; set; }
        public double PercentOfHighConfidenceAnswers { get; set; }

        public override string GetValue(int i)
        {
            switch (i)
            {
                case 0:
                    return this.Answers.ToString();
                    break;
                case 1:
                    return this.HighConfidenceAnswers.ToString();
                    break;
                case 2:
                    return this.PossibleAnswers.ToString();
                    break;
                case 3:
                    return this.NoAnswers.ToString();
                    break;
                case 4:
                    return this.PercentOfHighConfidenceAnswers.ToString() + "%";
                    break;
                default:
                    return "";
            }
        }
    }
    public class ResponseInfo : BaseReportInfo<ResponseItem>
    {
        public int TotalAnswers { get; set; }
        public int TotalHighConfidenceAnswers { get; set; }
        public int TotalPossibleAnswers { get; set; }
        public int TotalNoAnswers { get; set; }
        public double PercentOfHighConfidenceAnswers { get; set; }

        [JsonIgnore]
        public override List<string> FieldList
        {
            get
            {
                return new List<string>() {
                    "Answers","High Confidence Answers","Possible Answers","No Answers","% Of High Confidence Answers"
                };
            }
        }
        public override string GetValue(int i)
        {
            switch (i)
            {
                case 0:
                    return this.TotalAnswers.ToString();
                    break;
                case 1:
                    return this.TotalHighConfidenceAnswers.ToString();
                    break;
                case 2:
                    return this.TotalPossibleAnswers.ToString();
                    break;
                case 3:
                    return this.TotalNoAnswers.ToString();
                    break;
                case 4:
                    return this.PercentOfHighConfidenceAnswers.ToString()+"%";
                    break;
                default:
                    return "";
            }
        }
    }
    public class ResponseEntityInfo
    {
        public IList<EndpointAPIResponseRecordsOutputDto> ResponseEntityList { get; set; }
    }

    public class ResponseWrap : BasicWrap<ResponseItem, ResponseInfo, ResponseEntityInfo>
    {
        
        public static ResponseInfo GetResponse(SearchCriteria search, ResponseEntityInfo entityInfo, bool ifEncode = true)
        {
            //System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            //watch.Start();

            //ResponseourceEntityInfo entityInfo = ResponseourceProcess.GetResponseourceData(search); //数据库查询出来的数据

            //System.Diagnostics.Debug.WriteLine("Access Time: " + watch.Elapsed);
            //watch.Reset();
            //watch.Start();
            //System.Diagnostics.Debug.WriteLine(entityInfo.ResponseourceEntityList.Count);
            //System.Diagnostics.Debug.WriteLine(entityInfo.ResponseourceNumEntityList.Count);

            ResponseInfo result = new ResponseInfo();
            //UTCToLocal(ref entityInfo);
            switch (search.dimensionType)
            {
                case EnumDimensionType.ByTime://by time
                //case EnumDimensionType.AllChannel:
                //case EnumDimensionType.LivechatChannel:
                //case EnumDimensionType.DefaultChannel:
                //case EnumDimensionType.FacebookChannel:
                //case EnumDimensionType.TwitterChannel:
                    result = GetInfoByTime(search, entityInfo, PushByTimeData, null, null);
                    break;
            }

            //watch.Stop();
            //System.Diagnostics.Debug.WriteLine("Calc Time: " + watch.Elapsed);

            return result;
        }

        //search the chat Source info for campaign by criteria
        private static ResponseInfo GetResponseByDimension(SearchCriteria search, ResponseEntityInfo entityInfo, bool ifEncode)
        {
            var result = new ResponseInfo();
            //result.dataType = EnumReportDataType.DataByDimension;
            //List<EndpointAPIResponseRecordsOutputDto> data = entityInfo.ResponseEntityList.Where(a=>a.CodePlanId == int.Parse(search.filterStr)).ToList();

            //result.TotalResponse = data.Count;
            //if (search.dimensionType == EnumDimensionType.ByDepartment)
            //{
            //    result.TotalAgentOnly = data.Count(a=>a.ChatType== (int)EnumChatType.AgentOnly);
            //    result.TotalChatbotOnly = data.Count(a => a.ChatType == (int)EnumChatType.ChatbotOnly);
            //    result.TotalFromBotToAgent = data.Count(a => a.ChatType == (int)EnumChatType.ChatbotToAgent);
            //}

            //result.dataList = new List<ResponseItem>();

            //foreach (var item in data)
            //{
            //    var newItem = new ResponseItem();
            //    newItem.tableRowName = GetTableRowName(ifEncode, item.RequestTime);
            //    newItem.fieldId = item.FieldId;
            //    newItem.chatCount = item.Response;
            //    newItem.chatPercentage = CalcPercent(item.Response, result.totalChatCount);
            //    if (search.dimensionType == EnumDimensionType.ByDepartment)
            //    {
            //        newItem.fromChatButtonCount = item.ChatButtons;
            //        newItem.fromChatButtonPercentage = CalcPercent(item.ChatButtons, result.totalFromChatButtonCount);
            //        newItem.fromManuallyInvitationCount = item.ManuallyInvitations;
            //        newItem.fromManuallyInvitationPercentage = CalcPercent(item.ManuallyInvitations, result.totalFromManuallyInvitationCount);
            //        newItem.fromAutoInvitationCount = item.AutoInvitations;
            //        newItem.fromAutoInvitationPercentage = CalcPercent(item.AutoInvitations, result.totalFromAutoInvitationCount);
            //    }

            //    newItem.startTime = search.startDate.ToString();
            //    newItem.startTimeDate = search.startDate;
            //    newItem.endTime = search.endDate.ToString();
            //    newItem.endTimeDate = search.endDate;
            //    result.dataList.Add(newItem);
            //}

            //result.dataList = result.dataList.OrderByDescending(o => o.Time).ToList();
            return result;
        }

        private static ResponseInfo PushByTimeData(ResponseInfo result, ResponseEntityInfo entityInfo, SearchCriteria search)
        {
            IEnumerable<EndpointAPIResponseRecordsOutputDto> ResponseEntityList = entityInfo.ResponseEntityList.OrderBy(c => c.CallTime);
            int lindex = 0;
            foreach (var item in ResponseEntityList)
            {
                Guid operatorId = Guid.Empty;
                operatorId = SessionHelper.GetSessionValue_CurrentOperatorId();
                item.CallTime = DateTimeHelper.UtcToLocal(item.CallTime, operatorId); 

                ResponseItem responseItem = result.dataList[lindex];
                while (item.CallTime >= responseItem.endTimeDate && lindex < result.dataList.Count)
                {
                    lindex++;
                    responseItem = result.dataList[lindex];
                }
                responseItem.Answers++;
                result.TotalAnswers++;
                switch (item.AnswerType)
                {
                    case (int)EnumChatbotAnswerType.HighConfidenceAnswer:
                        responseItem.HighConfidenceAnswers++;
                        result.TotalHighConfidenceAnswers++;
                        break;
                    case (int)EnumChatbotAnswerType.PossibleAnser:
                        responseItem.PossibleAnswers++;
                        result.TotalPossibleAnswers++;
                        break;
                    case (int)EnumChatbotAnswerType.NoAnser:
                        responseItem.NoAnswers++;
                        result.TotalNoAnswers++;
                        break;
                    default:
                        break;
                }
            }

            foreach (ResponseItem item in result.dataList)
            {
                item.PercentOfHighConfidenceAnswers = CalcTwoPoint( CalcAvg(item.HighConfidenceAnswers, item.Answers, 4)*100);
            }

            result.dataList = result.dataList.Reverse().ToList();

            GetListTotal(ref result, search);
            return result;
        }

        private static ResponseInfo PushByTimeDataWith24_7Distribution(ResponseInfo result, ResponseEntityInfo entityInfo, SearchCriteria search)
        {
            int[] numDays = CountDays(search.startDate, search.endDate);
            foreach (EndpointAPIResponseRecordsOutputDto chatAction in entityInfo.ResponseEntityList)
            {
                Guid operatorId = Guid.Empty;
                operatorId = SessionHelper.GetSessionValue_CurrentOperatorId();
                DateTime requestTimeLocal = DateTimeHelper.UtcToLocal(chatAction.CallTime, operatorId); 

                int index = (int)requestTimeLocal.DayOfWeek * hournum + requestTimeLocal.Hour;

                result.dataList[index].Answers++;
                result.TotalAnswers++;
                switch (chatAction.AnswerType)
                {
                    case (int)EnumChatbotAnswerType.HighConfidenceAnswer:
                        result.dataList[index].HighConfidenceAnswers++;
                        result.TotalHighConfidenceAnswers++;
                        break;
                    case (int)EnumChatbotAnswerType.PossibleAnser:
                        result.dataList[index].PossibleAnswers++;
                        result.TotalPossibleAnswers++;
                        break;
                    case (int)EnumChatbotAnswerType.NoAnser:
                        result.dataList[index].NoAnswers++;
                        result.TotalNoAnswers++;
                        break;
                    default:
                        break;
                }          
            }

            foreach (ResponseItem item in result.dataList)
            {
                int num = numDays[item.IndexNum / hournum];
                if (num > 0)
                {
                    item.Answers = item.Answers;
                    item.HighConfidenceAnswers = item.HighConfidenceAnswers;
                    item.PossibleAnswers = item.PossibleAnswers;
                    item.NoAnswers = item.NoAnswers;
                    //item.PercentofHighConfidenceAnswer = string.Format("{0}%", CalcAvg(item.HighConfidenceAnswer, item.Answer) * 100 );
                    item.PercentOfHighConfidenceAnswers = CalcAvg(item.HighConfidenceAnswers, item.Answers);
                }
                else
                {
                    item.Answers = 0;
                    item.HighConfidenceAnswers = 0;
                    item.PossibleAnswers = 0;
                    item.NoAnswers = 0;
                    //item.PercentofHighConfidenceAnswer = string.Format("{0}%", 0);
                    item.PercentOfHighConfidenceAnswers = 0;
                }
                result.dataByTimeWithDistribution[item.IndexNum / hournum].dataByTimeList.Add(item);
            }
            result.dataList = new List<ResponseItem>();
            GetListTotal(ref result, search);
            return result;
        }

        private static ResponseInfo PushByTimeDataWith48HalfHourDistribution(ResponseInfo result, ResponseEntityInfo entityInfo, SearchCriteria search)
        {
            int dayNum = GetDays(search.startDate, search.endDate);

            foreach (EndpointAPIResponseRecordsOutputDto chatAction in entityInfo.ResponseEntityList)
            {
                Guid operatorId = Guid.Empty;
                operatorId = SessionHelper.GetSessionValue_CurrentOperatorId();
                DateTime requestTimeLocal = DateTimeHelper.UtcToLocal(chatAction.CallTime, operatorId); 

                int index = requestTimeLocal.Hour * 2 + (requestTimeLocal.Minute < 30 ? 0 : 1);

                result.dataList[index].Answers++;
                result.TotalAnswers++;
                switch (chatAction.AnswerType)
                {
                    case (int)EnumChatbotAnswerType.HighConfidenceAnswer:
                        result.dataList[index].HighConfidenceAnswers++;
                        result.TotalHighConfidenceAnswers++;
                        break;
                    case (int)EnumChatbotAnswerType.PossibleAnser:
                        result.dataList[index].PossibleAnswers++;
                        result.TotalPossibleAnswers++;
                        break;
                    case (int)EnumChatbotAnswerType.NoAnser:
                        result.dataList[index].NoAnswers++;
                        result.TotalNoAnswers++;
                        break;
                    default:
                        break;
                }

            }

            foreach (ResponseItem item in result.dataList)
            {
                if (dayNum > 0)
                {
                    item.Answers = item.Answers;
                    item.HighConfidenceAnswers = item.HighConfidenceAnswers;
                    item.PossibleAnswers = item.PossibleAnswers;
                    item.NoAnswers = item.NoAnswers;
                    //item.PercentofHighConfidenceAnswer = string.Format("{0}%", CalcAvg(item.HighConfidenceAnswer, item.Answer) * 100);
                    item.PercentOfHighConfidenceAnswers = CalcAvg(item.HighConfidenceAnswers, item.Answers);

                }
                else
                {
                    item.Answers = 0;
                    item.HighConfidenceAnswers = 0;
                    item.PossibleAnswers = 0;
                    item.NoAnswers = 0;
                    //item.PercentofHighConfidenceAnswer = string.Format("{0}%", 0);
                    item.PercentOfHighConfidenceAnswers = 0;
                }
            }

            GetListTotal(ref result, search);

            return result;
        }

        private static void GetListTotal(ref ResponseInfo result, SearchCriteria search)
        {
            double divNum = 0;
            if (search.timeUnit == EnumTimeIntervalType.Distribution24_7Hour)
            {
                divNum = GetWeeksInDateRange(search.startDate, search.endDate);
            }
            else if (search.timeUnit == EnumTimeIntervalType.Distribution48HalfHour)
            {
                divNum = GetDays(search.startDate, search.endDate);
            }
            else
            {
                result.TotalAnswers = result.TotalAnswers;
                result.TotalHighConfidenceAnswers = result.TotalHighConfidenceAnswers;
                result.TotalPossibleAnswers = result.TotalPossibleAnswers;
                result.TotalNoAnswers = result.TotalNoAnswers;
                result.PercentOfHighConfidenceAnswers = CalcTwoPoint(CalcAvg(result.TotalHighConfidenceAnswers, result.TotalAnswers,4)*100);
            }

            if (search.timeUnit == EnumTimeIntervalType.Distribution24_7Hour || search.timeUnit == EnumTimeIntervalType.Distribution48HalfHour)
            {
                result.TotalAnswers = result.TotalAnswers;
                result.TotalHighConfidenceAnswers = result.TotalHighConfidenceAnswers;
                result.TotalPossibleAnswers = result.TotalPossibleAnswers;
                result.PercentOfHighConfidenceAnswers = CalcTwoPoint(CalcAvg(result.TotalHighConfidenceAnswers, result.TotalAnswers,4)*100);
            }
        }

        #region export

        //search the New Export CSV Data for Chat Source Info by criteria
        public static NewExportCSVData GetExprotData(SearchCriteria search, ResponseEntityInfo entityInfo)
        {
            ResponseInfo info = GetResponse(search, entityInfo, false);               

            NewExportCSVData result = new NewExportCSVData(string.Empty, new List<NewCSVColumn>(), new DataTable());
            switch (search.dimensionType)
            {
                case EnumDimensionType.ByTime://by time
                case EnumDimensionType.ByDepartment://by department
                case EnumDimensionType.ChatbotChats://by department
                case EnumDimensionType.ChatbotAnswers://by department
                //case EnumDimensionType.AllChannel:
                //case EnumDimensionType.FacebookChannel:
                //case EnumDimensionType.LivechatChannel:
                //case EnumDimensionType.TwitterChannel:
                case EnumDimensionType.ChatbotHightFidenceAnswers://by department
                    {
                        result = GetExprotCSVData(search, info, info.FieldList);
                        break;
                    }
                case EnumDimensionType.RequestPage:
                    {
                        result = GetExprotCSVData(search, info, new List<string>() { info.FieldList[0] });
                        break;
                    }
            }
            return result;
        }

        #endregion

    }
}
